
class EventEmitter {
    constructor(){
        // 定义一个用来记录事件和监听器之间对应关系的实例变量
        this.events = { 
        }
    }
    on( name , handler ){
        // 首先尝试根据 name 获得 指定事件的监听器数组
        let handlerArray = this.events[name] ;
        // 若 handlerArray 不存在
        if( !handlerArray ) { // 注意最前方的感叹号
            // 则 为 handlerArray 赋值一个空数组
            handlerArray = [];
        }
        //  将当前绑定的事件监听器添加到 handlerArray 中
        handlerArray.push( handler );
        // 在 events 中建立 事件 和 监听器数组的对应关系
        this.events[ name ] = handlerArray ;
        console.log( this.events );
    }
    emit( name , ...params ){
        // 根据事件名称找到该事件对应的 监听器数组
        let handlerArray = this.events[ name ];
        if( handlerArray && handlerArray.length > 0 ) {
            // 创建自定义事件
            let evt = new Event( name );
            for( let i = 0 ; i < handlerArray.length ; i++ ){
                // 从监听器数组中获得函数
                let h = handlerArray[ i ];
                // 通过 call 来调用函数并将 事件对象 和 相关的参数传递给函数
                h.call( this , evt , ...params );
            }
        }
        // 若未找到相应事件的监听器则抛出异常
        // throw new Error( '未找到事件监听器' );
    }
    off( name , handler ) {
        // 根据事件名称找到该事件对应的 监听器数组
        let handlerArray = this.events[ name ];
        if( handlerArray ) {
            if( handlerArray.length == 1 ) {
                delete this.events[ name ];
                return ;
            }
            let index = handlerArray.findIndex( h => h === handler ) ;
            if( index ) {
                // 从监听器数组中删除单个监听器
                handlerArray.splice( index , 1 );
            }
        }
    }
}

const dispatcher = new EventEmitter();

const eventName = '开火' ;

const first = (evt,...params) => {
    console.log( 'first => event: ' , evt.type , " , params: " , ...params );
}
// 绑定事件监听器
dispatcher.on( eventName , first );

const second = (evt,...params) => {
    console.log( 'second => event: ' , evt.type , " , params: " , ...params );
}

// 绑定事件监听器
dispatcher.on( eventName , second );

// 触发事件并传递参数
dispatcher.emit( eventName , '弘姐' , '钰哥' , '盼盼');

dispatcher.off( eventName , second );

dispatcher.emit( eventName , '弘姐' , '钰哥' , '盼盼');

dispatcher.off( eventName , first );

dispatcher.emit( eventName , '弘姐' , '钰哥' , '盼盼');